#ifndef     __STORE_H
#define     __STORE_H

#include <string.h>
#include "../utils/md5.h"
#include "../pub_driver/flash.h"

namespace cfg {

template <typename T>
struct Box {
    T value;
    uint8_t md5_sum[16];

    bool verify() const {
       uint8_t sum[16];
       utils::md5::sum(&value, sizeof (T), sum);
       return memcmp(sum, md5_sum, 16) == 0;
    }

    void update() {
        utils::md5::sum(&value, sizeof (T), md5_sum);
    }
};

template <typename T, uint32_t FLASH_ADDR>
class Store {

public:
    inline T* operator->() {
        return &m_box.value;
    }

    Error load() {
		pub_driver::flash::read(FLASH_ADDR, &m_box, sizeof (m_box));
		bool ret = m_box.verify();
		if (!ret) {
			m_box.value.reset();
			return ec::pub::STORE_SUM_FAIL;
		}
		return ec::pub::OK;
    }

    Error erase() {
        return pub_driver::flash::erase(FLASH_ADDR, sizeof (m_box));
    }

    Error save() {

        Error err = pub_driver::flash::erase(FLASH_ADDR, sizeof (m_box));
        if (err) {
            return err;
        }
        m_box.update();
        err = pub_driver::flash::write(FLASH_ADDR, &m_box, sizeof (m_box));
        return err;
    }    

private:
    Box<T> m_box;
};

}

#endif
